﻿
package extremefx.modules {
	import extremefx.TimeSpan;
	import extremefx.events.MessageEventArgs;
	import extremefx.events.ObjectEventArgs;
	import extremefx.events.ProgressEventArgs;
	import extremefx.modules.BasePlayer;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.media.Sound;
	import flash.media.SoundLoaderContext;
	import flash.net.URLRequest;		

	/**
	 * @author Marcelo Volmaro
	 */
	public class SoundPlayer extends BasePlayer {
		private var _doneLoading:Boolean;
		private var _context:SoundLoaderContext;
		private var _sound:Sound;
		
		public function SoundPlayer() {
			super();
			_bufferLength = 1000;
			_context = new SoundLoaderContext(_bufferLength, false);
		}
		
		public function setUrl(pU:String):void {
			if (_url == pU) return;
		
			_url = pU;
			_firstPlay = true;
		
			if (_isPlaying) {
				stop();
				_sound = null;
			}
		}
		
	    public function get position():TimeSpan{
	    	return new TimeSpan(_soundChannel.position || 1);
		}
		
		public function set position(pP:TimeSpan):void{
    		_position = pP.ticks;
    		_play();
    		_soundChannel.stop();

        	if (_isPlaying) {
            	play();
        	}
		}
		
		public function get duration():TimeSpan {
			return new TimeSpan(_sound.length || 0);
		}
		
		public function set bufferLength(pValue:Number): void { 
			_bufferLength = pValue;
			_context.bufferTime = pValue;
		}
		
		private function _play():void {
			_soundChannel.removeEventListener(Event.SOUND_COMPLETE, soundComplete);
			_soundChannel = _sound.play(Math.round(_position / 1000), 0, _soundTransform);
			_soundChannel.addEventListener(Event.SOUND_COMPLETE, soundComplete, false, 0, true);
		}

		public function play():void {
			if (_url && _url != ""){
				if (_firstPlay){
					var request:URLRequest = new URLRequest(_url);
					_position = 0;
					_sound = new Sound();
					_sound.addEventListener(Event.COMPLETE, completeHandler, false, 0, true);
	            	_sound.addEventListener(Event.ID3, setID3, false, 0, true);
	            	_sound.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
	            	_sound.addEventListener(ProgressEvent.PROGRESS, updatePos, false, 0, true);
					
					_sound.load(request, _context);
					_firstPlay = false;
					
					if (_eOnOpen) _eOnOpen.fire();
				}
				
				_doneLoading = false;
				_isPlaying = true;
				_play();
			}
		}
		
		private function ioErrorHandler(errorEvent:IOErrorEvent):void {
			if (_eOnError) _eOnError.fire(new MessageEventArgs(errorEvent.text));	
		}

		private function completeHandler(pEvent:Event):void {
			if (_eOnComplete) _eOnComplete.fire();
		}

		private function updatePos(event:ProgressEvent):void {
			var p:ProgressEventArgs = new ProgressEventArgs(event.bytesLoaded, event.bytesTotal);
			
			if (isNaN(p.percent)) return;
			
			if (_eOnProgress) _eOnProgress.fire(p);

			if (p.percent == 1 && !_doneLoading) {
				_doneLoading = true;
			}
		}
		
		private function setID3():void {
			_metadata = _sound.id3;
			if (_eOnMetaData) _eOnMetaData.fire(new ObjectEventArgs(_metadata));
		}
		
		public function get metadata():Object {
			return _metadata;
		}
	
		private function soundComplete(pEvent:Event):void{
			if (_eOnPlayComplete) _eOnPlayComplete.fire();
			
			stop();
			if (_loop) play();
		}
		
		public function pause():void {
			_position = _soundChannel.position;
			_soundChannel.stop();
			_isPlaying = false;
		}
		
		public function stop():void {
			_position = 0;
			_play();
			_soundChannel.stop();
			_isPlaying = false;
		}
		
		public function destroy():void {
			stop();
			_sound = null;
		}
		
		public function set volume(volume:Number):void {
			_volume = volume;
			_soundTransform.volume = volume;
		}
		
		
	}
}
